﻿using System;
using System.Collections;
using System.Collections.Generic;

namespace K.Client
{
    public class Incremental_ObjId_Policy
    {
        private int mStartId;
        private int mCount;
        private int mEndId;
        int mLast_UsedId;

        public Incremental_ObjId_Policy(int objType, int count)
        {
            mStartId = (objType << KObj.OBJ_ID_BITS) + 1;
            mEndId = ((objType + 1) << KObj.OBJ_ID_BITS) - 10;
            mCount = count;
        }

        /*
        * 获取一个有效的对象id
        * @param offset 对象在数组中的索引(偏移量)
        * @return 有效的对象ID
        */
        public int GetValidId(int offset)
        {
            int tmp_Id = mStartId + offset;
            if (tmp_Id <= mLast_UsedId)
            {
                int real_Id = tmp_Id + ((mLast_UsedId - tmp_Id) / mCount + 1) * mCount;
                if (real_Id < mEndId) { tmp_Id = real_Id; }
            }
            mLast_UsedId = tmp_Id;
            return tmp_Id;
        }

        /*
        * 获取一个有效的对象偏移量
        * @param objID     有效的对象ID
        * @return 对象在数组中的索引(偏移量)
        *         失败返回-1
        */
        public int GetOffsetValue(int id)
        {
            if (id < mStartId || id > mEndId)
            {

            }
            return (id - mStartId) % mCount;
        }
    };

    public class ObjPool<T> where T : KObj, new()
    {
        private Stack<T> mUnUsedList;
        private Dictionary<long, T> mUsedList;
        private int mObjType;
        private long mIdx;

        public ObjPool(int nType)
        {
            mObjType = nType;
            mIdx = ((long)nType) << 56;
            mUnUsedList = new Stack<T>();
            mUsedList = new Dictionary<long, T>();
        }

        public T CreateObject()
        {
            T o = null;
            if (mUnUsedList.Count > 0)
            {
                o = mUnUsedList.Pop();
            }
            else
            {
                o = new T();
            }
            ++mIdx; o.ObjId = mIdx;
            mUsedList[mIdx] = o;
            o.Init(); return o;
        }

        public void DestroyObject(long nObjID)
        {
            if (mUsedList.ContainsKey(nObjID))
            {
                mUnUsedList.Push(mUsedList[nObjID]);
                mUsedList.Remove(nObjID);
            }
        }

        public T GetObject(long nObjID)
        {
            T o = null;
            if (mUsedList.TryGetValue(nObjID, out o))
            {
                return o;
            }
            else
            {
                return null;
            }
        }

        public Dictionary<long, T>.KeyCollection GetKeys()
        {
            return mUsedList.Keys;
        }

        public Dictionary<long, T>.ValueCollection GetValues()
        {
            return mUsedList.Values;
        }
    }

    public class ObjPool2<T> where T : new()
    {
        private KObj mObjType;
        private int mSize;

        private Incremental_ObjId_Policy mPolicy;
        private Dictionary<Int64, KObj> mDictionary;
        private ArrayList arrayItemList;
        private ArrayList arrayEmptyList;

        public ObjPool2(int objtype, Int32 size)
        {
            mPolicy = new Incremental_ObjId_Policy(objtype, size);
            mDictionary = new Dictionary<long, KObj>(); mSize = size;
            arrayItemList = new ArrayList(mSize);
            arrayEmptyList = new ArrayList(mSize);

            //初始化对象池
            for (int i = 0; i < size; ++i)
            {
                mObjType = (KObj)Activator.CreateInstance(typeof(T));
                arrayItemList.Add(mObjType);
                arrayEmptyList.Add(i);
            }
        }

        public KObj CreateObject()
        {
            if (arrayEmptyList.Count <= 0)
            {
                //没有可用对象池
                return null;
            }
            int nIndex = (int)arrayEmptyList[0];
            KObj oneObject = (KObj)arrayItemList[nIndex];
            oneObject.ObjId = (mPolicy.GetValidId(nIndex));//设置ID

            mDictionary.Add(oneObject.ObjId, oneObject);
            arrayEmptyList.RemoveAt(0);
            return oneObject;
        }

        public void RealseObject(Int64 objId)
        {
            KObj find;
            if (mDictionary.TryGetValue(objId, out find))
            {
                if (find.IsValid())
                {
                    find.InValid();
                }
                mDictionary.Remove(objId);

                int nIndex = arrayItemList.IndexOf(find);
                arrayEmptyList.Add(nIndex);
            }
        }
    }
}